package com.kelp.codetoolkit.config

import com.intellij.openapi.options.Configurable
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.ComboBox
import com.intellij.openapi.ui.Messages
import com.intellij.ui.JBColor
import com.intellij.util.ui.FormBuilder
import com.kelp.codetoolkit.enums.OrmFrameworkEnum
import com.kelp.codetoolkit.enums.RemoteInvocationFrameworkEnum
import com.kelp.codetoolkit.respository.CodeToolkitGlobalSettingRepository
import com.kelp.codetoolkit.utils.ProjectUtil
import java.awt.FlowLayout
import java.awt.Font
import java.awt.event.ActionEvent
import java.awt.event.ActionListener
import javax.swing.*
import javax.swing.event.DocumentEvent
import javax.swing.event.DocumentListener

/**
 * @author: liuyuebai
 * @date: 2024/12/29 09:23
 * @description:
 */
class CodeToolkitGlobalConfig(project: Project): Configurable {

    private val globalSettingState = CodeToolkitGlobalSettingRepository.getInstance(project).state

    private val pageSettingLabel = JLabel("Paging Wrapper Setting：")
    private val pageSettingContent = JTextField(25)
    private val exampleBlankSettingLabel = JLabel("                        ")
    private val examplePageLabel = JLabel("Paging Setting Example : com.*.*.Page")

    private val viewResponseSettingLabel = JLabel("View Wrapper Setting：")
    private val viewResponseSettingContent= JTextField(25)
    private val exampleViewBlankSettingLabel = JLabel("                      ")
    private val viewResponseExampleSettingLabel = JLabel("View Wrapper Setting Example : com.*.*.CommonResponse")


    //-------------------select orm-------------------------
    private val ormPanel = JPanel(FlowLayout(FlowLayout.LEFT))
    private val ormLabel = JLabel("ORM Framework：")
    private val ormButtonGroup = ButtonGroup()
    private val mybatis = JRadioButton("MyBatis")
    private val mybatisPlus = JRadioButton("MyBatis-Plus")

    //-------------------select orm-------------------------

    //-------------------select Microservice framework-------------------------
    private val microServicePanel = JPanel(FlowLayout(FlowLayout.LEFT))
    private val microServiceLabel = JLabel("Remote Invocation Framework：")
    private val microServiceButtonGroup = ButtonGroup()
    private val dubbo = JRadioButton("Dubbo")
    private val openfeign = JRadioButton("OpenFeign")
    //-------------------select orm-------------------------
    //-------------------dubbo------------------------------
    private val stubModuleLabel = JLabel("Dubbo Stub Module：")
    private var stubModule: ComboBox<String> = ComboBox()

    private val stubLabel = JLabel("Provider File Parent：")
    private val stubPackageName = JTextField(25)
    private val stubBlankExample = JLabel("                ")
    private val stubExample = JLabel("Provider File Parent Default: com.*.*.stub.provider")
    //-------------------dubbo------------------------------
    private var selectOrm:String = ""
    private var selectRemoteInvocationFramework:String=""

    private var isModified = true

    init {

        handleDubboVisible(false)
        // 为每个单选按钮添加动作监听器
        val ormActionListener = ActionListener { e ->
            val selectedButton = e.source as? JRadioButton
            selectedButton?.let {
                selectOrm = it.text
                isModified = true
            }
        }
        mybatis.addActionListener(ormActionListener)
        mybatisPlus.addActionListener(ormActionListener)

        // 为每个单选按钮添加动作监听器
        val mircoServiceActionListener = ActionListener { e ->
            val selectedButton = e.source as? JRadioButton
            selectedButton?.let {
                selectRemoteInvocationFramework = it.text
                if (RemoteInvocationFrameworkEnum.DUBBO.value == it.text){
                    initModuleComboBox(project)
                    handleDubboVisible(true)
                    stubPackageName.text = globalSettingState.getStubPackage()
                }else{
                    stubModule.selectedItem = ""
                    stubPackageName.text = ""
                    handleDubboVisible(false)
                }
                isModified = true
            }
        }
        dubbo.addActionListener(mircoServiceActionListener)
        openfeign.addActionListener(mircoServiceActionListener)

        pageSettingContent.text = globalSettingState.getPageSetting()
        viewResponseSettingContent.text = globalSettingState.getViewResponseSetting()


        selectOrm = globalSettingState.getOrmSetting()
        selectRemoteInvocationFramework = globalSettingState.getRemoteInvocationFramework()
        if (RemoteInvocationFrameworkEnum.DUBBO.value == globalSettingState.getRemoteInvocationFramework()){
            handleDubboVisible(true)
            stubPackageName.text = globalSettingState.getStubPackage()
            stubModule.addItem(globalSettingState.getStubModuleName())
        }
        if (OrmFrameworkEnum.MyBatis.value == globalSettingState.getOrmSetting()) {
            mybatis.setSelected(true)
        }
        if (OrmFrameworkEnum.MyBatisPlus.value == globalSettingState.getOrmSetting()) {
            mybatisPlus.setSelected(true)
        }
        if (RemoteInvocationFrameworkEnum.DUBBO.value == globalSettingState.getRemoteInvocationFramework()) {
            dubbo.setSelected(true)
        }
        if (RemoteInvocationFrameworkEnum.OPENFEIGN.value == globalSettingState.getRemoteInvocationFramework()) {
            openfeign.setSelected(true)
        }
        val listener = object : DocumentListener {
            override fun insertUpdate(e: DocumentEvent) {
                isModified = true
            }
            override fun removeUpdate(e: DocumentEvent) {
                isModified = true
            }
            override fun changedUpdate(e: DocumentEvent) {
                isModified = true
            }
        }
        // 添加请求参数文档监听器到输入框
        pageSettingContent.document.addDocumentListener(listener)
        viewResponseSettingContent.document.addDocumentListener(listener)

        // 监听 ComboBox 的选中事件
        stubModule.addActionListener{event: ActionEvent ->
            // 获取触发事件的 ComboBox
            val source = event.source as ComboBox<*>
            // 获取当前选中的项
            val selectedItem = source.selectedItem as String
           stubPackageName.text = selectedItem.replace("-","")
        }

    }

    override fun createComponent(): JComponent {
        // 创建一个浅灰色的颜色对象
        examplePageLabel.foreground = JBColor.GRAY
        examplePageLabel.setFont(Font("Monospaced", Font.PLAIN, 14))
        // 创建一个浅灰色的颜色对象
        viewResponseExampleSettingLabel.foreground = JBColor.GRAY
        viewResponseExampleSettingLabel.setFont(Font("Monospaced", Font.PLAIN, 14))

        stubExample.foreground = JBColor.GRAY
        stubExample.setFont(Font("Monospaced", Font.PLAIN, 14))

        mybatis.border = BorderFactory.createEmptyBorder(0, 0, 0, 10)
        ormPanel.add(ormLabel)
        ormButtonGroup.add(mybatis)
        ormButtonGroup.add(mybatisPlus)
        ormPanel.add(mybatis)
        ormPanel.add(mybatisPlus)

        dubbo.border = BorderFactory.createEmptyBorder(0, 0, 0, 10)
        microServiceButtonGroup.add(dubbo)
        microServiceButtonGroup.add(openfeign)
        microServicePanel.add(dubbo)
        microServicePanel.add(openfeign)

        val mainPanel = FormBuilder.createFormBuilder()
            .addLabeledComponent(pageSettingLabel,pageSettingContent)
            .addLabeledComponent(exampleBlankSettingLabel,examplePageLabel,0,false)
            .addLabeledComponent(viewResponseSettingLabel,viewResponseSettingContent)
            .addLabeledComponent(exampleViewBlankSettingLabel,exampleViewBlankSettingLabel,0,false)
            .addLabeledComponent(exampleViewBlankSettingLabel,viewResponseExampleSettingLabel)
            .addLabeledComponent(ormLabel,ormPanel)
            .addLabeledComponent(microServiceLabel,microServicePanel)
            .addLabeledComponent(stubModuleLabel,stubModule)
            .addLabeledComponent(stubLabel,stubPackageName)
            .addLabeledComponent(stubBlankExample,stubExample)
            .addComponentFillVertically(JPanel(),0).panel
        return mainPanel
    }

    override fun isModified(): Boolean {
       return isModified
    }

    override fun apply() {
        globalSettingState.setPageSetting(pageSettingContent.text)
        globalSettingState.setViewResponseSetting(viewResponseSettingContent.text)
        globalSettingState.setOrmSetting(selectOrm)
        globalSettingState.setRemoteInvocationFramework(selectRemoteInvocationFramework)
        isModified = false
        if (RemoteInvocationFrameworkEnum.DUBBO.value == selectRemoteInvocationFramework){
            val stubModuleName = stubModule.selectedItem as String
            var stubName = stubPackageName.text
            if (stubName.isBlank()){
                stubName = stubModuleName.replace("-","")
            }
            globalSettingState.setStubPackage(stubName)
            globalSettingState.setStubModuleName(stubModuleName)
        }else{
            globalSettingState.setStubPackage("")
            globalSettingState.setStubModuleName("")
        }
    }

    override fun getDisplayName(): String {
        return "Code Toolkit Config"
    }

    override fun reset() {
        globalSettingState.setPageSetting("")
        globalSettingState.setViewResponseSetting("")
        globalSettingState.setOrmSetting("")
        globalSettingState.setRemoteInvocationFramework("")
        globalSettingState.setStubModuleName("")
        super.reset()
        isModified = true
    }

    private fun handleDubboVisible(viewShow:Boolean){
        stubModuleLabel.isVisible = viewShow
        stubModule.isVisible = viewShow
        stubLabel.isVisible = viewShow
        stubPackageName.isVisible = viewShow
        stubExample.isVisible = viewShow
    }

    private fun initModuleComboBox(project: Project){
        val moduleList = ProjectUtil.getProjectSubModules(project)
        if (moduleList.size<2){
            Messages.showErrorDialog(project,"Please confirm whether the remote call of the current project uses the Dubbo framework.","ERROR")
            throw Exception("Please confirm whether the remote call of the current project uses the Dubbo framework.")
        }
        val moduleNames: MutableList<String> = ArrayList()
        val model = stubModule.model
        val size = model.size
        for (i in 0 until size) {
            moduleNames.add(model.getElementAt(i) as String)
        }
        for (module in moduleList){
            if (!moduleNames.contains(module.name)){
                stubModule.addItem(module.name)
            }
        }
    }
}